/*
 * lcd_self.c
 *
 *  Created on: Mar 4, 2025
 *      Author: Carrier Len
 */
#include "main.h"
#include "key_led.h"
#include "file_opera.h"
#include "ff.h"
#include "lcd.h"
#include <stdio.h>

#ifdef user_FreeRTOS

#include "FreeRTOS.h"
#include "semphr.h"
#include "queue.h"
#include "cmsis_os.h"
#include "semphr.h"
#include "queue.h"

extern osThreadId_t Task_SD_WriteHandle;
extern osMessageQueueId_t Queue_KeyNumbersHandle;
extern osMessageQueueId_t Queue_FileTypeWritingHandle;
extern osMessageQueueId_t Queue_FileEventHandle;
extern osSemaphoreId_t BinSem_usart3_getHandle;

extern fifo_s_t file_name_fifo;
extern FIL file;
/*
 * 用于使用LCD打印部分信息
 * key_right :
 * key_up    :
 * key_left  :
 * key_down  : 显示上位机传来的CMD信息
 */
void AppTask_LCD_Display(void *argument)
{
	keys key = key_none;
	for (;;)
	{
		if (xQueueReceive(Queue_KeyNumbersHandle, &key, portMAX_DELAY))
		{
			if(key == key_right)
			{

			}
			if(key == key_up)
			{

			}
			else if(key == key_left)
			{

			}
			else if(key == key_down)
			{
				char *str_mes;
				uint8_t strraw[50] = {0};
				FRESULT res = fatTest_ReadTXTFile("log.txt", strraw, sizeof(strraw));
				if(res == FR_OK)
				{
					str_mes = strrchr((char *)strraw,'+');
					str_mes = strstr(str_mes,":") + 1;
					lcd_show_string(30, 24*8, 24*12, 24, 24, "                             ", BLACK);
					lcd_show_string(30, 24*8, 24*12, 24, 24, str_mes, BLACK);
				}
				else if(res == FR_LOCKED)
				{
					uint8_t show_str[] = "File is locked!";
					lcd_show_string(30, 24*7, 240, 24, 24, (char*) show_str, RED);
				}
			}
		}
		osDelay(100);
	}
}

/*
 * 用于确认某一数组中的element个元素是否相等
 */
static uint8_t is_array_equal(uint32_t *arr, uint16_t element)
{
	uint32_t first_element = arr[0];
    for (uint16_t i = 1; i < element; i++)
    {	if (arr[i] != first_element) {return 0;}	}
    return 1;
}

/*
 * 用于使用LCD显示SD卡写数据进度，包含以下功能
 * 1、实时显示当前传输文件的文件大小，单位byte
 * 2、实时显示文件传输进度，单位%
 * 3、检测文件约3s时间内大小没有变化，根据传输进度发送full状态或break状态至AppTask_SD_Write线程
 * 4、接收AppTask_SD_Write线程传来的，数据丢包异常或文件传输完成事件，并显示
 */
void AppTask_LCD_ShowWavSize(void *argument)
{
	uint32_t file_totalSize = 0;
	uint32_t file_previousSize[10] = {0};
	uint32_t file_currentSize = 0;
	double_t file_downloadPerc = 0;
	double_t file_Perc_front = 0;
	uint8_t file_name[30] = {0};
	uint8_t show_str_size[40];
	uint8_t show_str_perc[40];
	filetypes file_type_writing;
	fifo_s_init(&file_name_fifo, file_name, sizeof(file_name));

	for (;;)
	{
		uint32_t EnterClear = 0x00000000;
		uint32_t ExitClear = 0xFFFFFFFF;
		if(xTaskNotifyWait(EnterClear, ExitClear, &file_totalSize, portMAX_DELAY) == pdPASS)
		{	//仅在AppTask_SD_Write任务中被唤醒，当检测到有文件需要传输时
			uint16_t fifo_len = 0;
			fifo_len = fifo_s_used(&file_name_fifo);
			fifo_s_gets(&file_name_fifo, (char *)file_name, fifo_len);			//获取当前传输的文件名
			lcd_fill(30, 40, 30+24*12, 40+30*2, WHITE);
			sprintf((char*)show_str_size, "Size: %ld", file_totalSize);			//显示当前文件的大小
			lcd_show_string(30, 40 + 0 * 30, 240, 24, 24, (char*) show_str_size, BLACK);
			sprintf((char*)show_str_perc, "Progress: ");
			lcd_show_string(30, 40 + 1 * 30, 240, 24, 24, (char*) show_str_perc, BLACK);
			osDelay(pdMS_TO_TICKS(1000));
			while(1)
			{
				static uint8_t loop = 0;
				file_currentSize = f_size(&file);
				file_downloadPerc = (double_t)file_currentSize / file_totalSize * 100;
				//显示传输进度，以%形式
				sprintf((char*)show_str_perc, "%d%%", (uint8_t)file_downloadPerc);
				lcd_show_string(30 + 24*5, 40 + 1*30, 240, 24, 24, (char*) show_str_perc, BLACK);
				osDelay(pdMS_TO_TICKS(300));
				//仅在AppTask_SD_Write任务中被赋值，用于在各个线程中同步当前文件传输状态
				BaseType_t queue_res = xQueuePeek(Queue_FileTypeWritingHandle, &file_type_writing, 0);
				if(queue_res == pdTRUE)
				{
					if(file_type_writing == file_wav_end)
					{	//AppTask_SD_Write任务检测到终止符，文件传输完成
						sprintf((char*)show_str_perc, "Progress: %d%% OK!", (uint8_t)file_Perc_front);
						lcd_show_string(30, 40 + 1 * 30, 240, 24, 24, (char*) show_str_perc, RED);
						break;
					}
					else if(file_type_writing == file_wav_break)
					{	//AppTask_SD_Write中途传输失败
						sprintf((char*)show_str_perc, "Progress: %d%% break!", (uint8_t)file_Perc_front);
						lcd_show_string(30, 40 + 1 * 30, 240, 24, 24, (char*) show_str_perc, RED);
						break;
					}
				}
				file_Perc_front = file_downloadPerc;
				file_previousSize[loop] = file_currentSize;
				loop++;
				if(loop == 10) loop = 0;

				if(is_array_equal(file_previousSize, sizeof(file_previousSize) / sizeof(file_previousSize[0])))
				{	//文件大小已有3s未有变化，需触发相应事件
					memset(file_previousSize, 0, sizeof(file_previousSize) - sizeof(file_previousSize[0]));
					if(file_downloadPerc > 95)
					{	//传输进度大于95%，认为已经基本传输完成，但未接收到终止符，可以中止传输了
						filetypes fileEvent = file_wav_full;
						xQueueOverwrite(Queue_FileEventHandle, &fileEvent);	//向AppTask_SD_Write线程传输文件已写完事件
						xSemaphoreGive(BinSem_usart3_getHandle);			//让AppTask_SD_Write线程转为就绪态
						break;
					}
					else
					{	//传输进度不足95%，需中止传输，待上位机重新发送
						filetypes fileEvent = file_wav_break;
						xQueueOverwrite(Queue_FileEventHandle, &fileEvent);	//向AppTask_SD_Write线程传输写文件中断事件
						xSemaphoreGive(BinSem_usart3_getHandle);			//让AppTask_SD_Write线程转为就绪态
						break;
					}
				}
			}
		}
		osDelay(100);
	}
}

#endif
